/*  Last edited: Jan 16 11:42 1997 (il) */
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <ctype.h>
#include <limits.h>
#include "fpp.h"
#include "dirent.h"

extern int graphQueryOpen();
extern void suffixremove();
extern int save_fpc();

int dirbox,filebox,currentbox;
Graph gnew=0;
BOOL dirokay,fileokay;

void getnewproj(void);
void mergethetwo(void);
void savenew(void);
BOOL mergecorandsave(void);
BOOL getfirstcor(void);
BOOL getsecondcor(void);
BOOL getnamesoffiles(void);
void SetCtgForMatchingClones4(void);
int readsecond(void);
void recalccontigs(void);
void markersetzero(void);
void markercorrect(void);
void sortoutmarkersman(void);
void copydirectorys(void);
int save_fpc_safe(void);
void contigsAlloc(int ctg);

void checkdir(char *temp)
{
  struct stat stbuf;

  if(stat(newdirName, &stbuf) == -1){
    displaymess("ERROR directory does not exist");
    displaymess("Try again");
    dirokay = FALSE;
  }
  else
    dirokay = TRUE;
}

void checkproj(char *temp)
{
  struct stat stbuf;
  char str1[FIL_BUFFER_SIZE];
  int num;
  int i;

  if(stat(messprintf("%s/%s",newdirName,newfileName),&stbuf) != -1){
    displaymess("Project Directory already exists");
    displaymess("This is not allowed. Try again");
    fileokay = FALSE;
  }
  else{
    if(strlen(newfileName) > 0){
      if(strstr(newfileName,"/")!= NULL){
	num = strlen(newfileName);
	for(i=0;i<num;i++){
	  if(newfileName[i] == '/')
	    break;
	}
	newfileName[i] = '\0';
	sprintf(str1,"Use proj = %s. To create a NEW dir %s with proj %s.fpc in it.",newfileName,newfileName,newfileName);
	/* sness */
	/*if(graphQuery(str1)){ */
	if(messQuery(str1)){
	  checkproj(newfileName);
	  return;
	}
	else
	  fileokay = FALSE;
      }
      else if(strstr(newfileName,".fpc")!=NULL){
	num = strlen(newfileName);
	for(i=0;i<num;i++){
	  if(newfileName[i] == '.' && newfileName[i+1] == 'f' && newfileName[i+2] == 'p' && newfileName[i+3] == 'c') 
	    break;
	}
	newfileName[i] = '\0';	
	sprintf(str1," NO extension needed. Try with %s",newfileName);
	/* sness */
	/*if(graphQuery(str1)){ */
	if(messQuery(str1)){
	  checkproj(newfileName);
	  return;
	}
	else
	  fileokay = FALSE;
      }
      else
	fileokay = TRUE;
    }
    else
      fileokay = FALSE;
  }
}

void contnamebit()
{
  char temp[2];
  checkdir(temp);
  checkproj(temp);
  if(!dirokay)
    return;
  if(!fileokay)
    return;
  else{
    graphDestroy();
    if(getnamesoffiles()){
      if(getfirstcor()){
	if(getsecondcor()){
	  if(readsecond()){
	    mergethetwo();
	    max_contig += max_contig2;
	    recalccontigs();
	    markersetzero();       /* initialise marker for correction */
	    markercorrect();       /* get new clone index's for these markers */
	    sortoutmarkersman();   /* position the markers */
	    copydirectorys();
	    mergecorandsave();
	    savenew();
	  }
	}
      }
    }
  }
}

void quitnamebit()
{
  graphDestroy();
}

void newpick(int box, float x, float y)
{
  if(box != 0){
    currentbox = box;
    getnewproj();
  }
}

void getnewproj()
{
  static MENUOPT menu2[] = {
    { quitnamebit, "Close"},
    { contnamebit, "Continue"}, 
    { 0, 0 } };
  int i;
  int l;
  BOOL past;
  char *cp;
  
  if(!graphActivate(gnew)){
    dirokay = TRUE;
    fileokay = FALSE;
    l = strlen(dirName);
    past = FALSE;
    if(l <= 0){
      cp = getenv("PWD");
      strcpy(dirName,cp);
      l = strlen(dirName);
    }
    if(l > 0){
      for(i=l;i>=0;i--){
	if(!past){
	  if(dirName[i]=='/'){
	    past = TRUE;
	    newdirName[i]=dirName[l];
	  }
	}
	else
	  newdirName[i]=dirName[i];
      }
    }
    else{
      printf("WOW big error\n");
      dirokay = FALSE;
    }
    strcpy(newfileName,"");
    gnew = graphCreate (TEXT_SCROLL,"New Project Data",.6,.6,.8,.2) ; 
    graphRegister(PICK,newpick);
    graphMenu(menu2);
  }
  else
    graphClear();

  if(currentbox == dirbox){
    graphText("Project/Dir name",2.0,5.0);
    filebox = graphTextEntry(newfileName, FIL_BUFFER_SIZE+1, 4.0, 6.0,checkproj);   
    
    graphText("Top Directory",2.0,2.0);
    dirbox = graphTextEntry(newdirName, DIR_BUFFER_SIZE+1, 4.0, 3.0,checkdir);   
  }
  else{    
    graphText("Top Directory",2.0,2.0);
    dirbox = graphTextEntry(newdirName, DIR_BUFFER_SIZE+1, 4.0, 3.0,checkdir);   

    graphText("Project name (will create a NEW directory and file name for this)",2.0,5.0);
    filebox = graphTextEntry(newfileName, FIL_BUFFER_SIZE+1, 4.0, 6.0,checkproj);   
  }
  
  graphButton("Close",quitnamebit,2.0,8.0);
  graphButton("Continue",contnamebit,8.0,8.0);
  graphRedraw();
}
  
BOOL getnamesoffiles()
{
  BOOL carryon = FALSE;
  char temp[DIR_BUFFER_SIZE];

  strcpy(temp,newdirName);
  sprintf(newdirName,"%s/%s",temp,newfileName);

  fpsecond  = (FILE *)graphQueryOpen(dirName3,secondfileName,"fpc","r","merge file name"); 
  /* sness */
  suffixremove(secondfileName);
  if(fpsecond != NULL){
    carryon = TRUE;
  }
  else{
    displaymess("ERROR opening second merge file");
    printf("ERROR opening second merge file\n");
  }
  if(!carryon)
    return FALSE;
  else 
    return TRUE;
}

void copydirectorys()
{
  char str1[180],from[180],to[180];
  struct stat stbuf;
  DIR *dfd;
  struct dirent *dp2;
  int i;
  FILE *fileptr;


/* first make directorys and copy original data */
  if(strlen(dirName) >0){
    sprintf(str1,"mkdir %s",newdirName);
    system(str1);
    sprintf(str1,"mkdir %s/Image",newdirName);
    system(str1);
    if(stat(messprintf("%s/Image",dirName),&stbuf) != -1){
      sprintf(str1,"cp %s/Image/* %s/Image",dirName,newdirName);
      system(str1);
    }
    sprintf(str1,"mkdir %s/Bands",newdirName);
    system(str1);
    if(stat(messprintf("%s/Bands",dirName),&stbuf) != -1){
      sprintf(str1,"cp %s/Bands/* %s/Bands",dirName,newdirName);
      system(str1);
    }
    sprintf(str1,"mkdir %s/Gel",newdirName);
    system(str1);
    if(stat(messprintf("%s/Gel",dirName),&stbuf) != -1){
      sprintf(str1,"cp %s/Gel/* %s/Gel",dirName,newdirName);
      system(str1);
    }
  }
  else{
    sprintf(str1,"mkdir %s",newdirName);
    system(str1);
    sprintf(str1,"mkdir %s/Image",newdirName);
    system(str1);
    sprintf(str1,"cp ./Image/* ../%s/Image",newfileName);
    system(str1);
    sprintf(str1,"mkdir ../%s/Bands",newfileName);
    system(str1);
    sprintf(str1,"cp ./Bands/* ../%s/Bands",newfileName);
    system(str1);
    sprintf(str1,"mkdir ../%s/Gel",newfileName);
    system(str1);
    sprintf(str1,"cp ./Gel/* ../%s/Gel",newfileName);
    system(str1);
  }
/* next do same for second set */
/* but i need to check that the names do not clash */
  for(i=0;i<3;i++){
    if(i==0){
      if(strlen(dirName3)>0)
	sprintf(from,"%s/Image",dirName3);
      else
	sprintf(from,"./Image");
      if(strlen(newdirName) > 0)
	sprintf(to,"%s/Image",newdirName);
      else
	sprintf(to,"./Image");
    }
    else if(i==1){
      if(strlen(dirName3)>0)
	sprintf(from,"%s/Bands",dirName3);
      else
	sprintf(from,"./Bands");
      if(strlen(newdirName) > 0)
	sprintf(to,"%s/Bands",newdirName);
      else
	sprintf(to,"./Bands");      
    }
    else{
      if(strlen(dirName3)>0)
	sprintf(from,"%s/Gel",dirName3);
      else
	sprintf(from,"./Gel");
      if(strlen(newdirName) > 0)
	sprintf(to,"%s/Gel",newdirName);
      else
	sprintf(to,"./Gel");
    }
    
    if( (dfd = opendir(from)) == NULL){
      printf("ERROR cant open %s\n",from);
      return;
    }
    while (( dp2 = readdir(dfd)) != NULL) {
      if(strcmp(dp2->d_name,".") == 0
	 || strcmp(dp2->d_name,"..") == 0)
	continue;
      if(i==0 || i==1){
	if(strstr(dp2->d_name,"bands")){
	  if((fileptr = fopen(messprintf("%s/%s",to,dp2->d_name),"r")) == NULL){
	    /* copy this one */
	    sprintf(str1,"cp %s/%s %s/%s",from,dp2->d_name,to,dp2->d_name);
	    system(str1);
	  }
	  else{
	    /* copy but add prefix */
	    sprintf(str1,"cp %s/%s %s/a%s",from,dp2->d_name,to,dp2->d_name);
	    system(str1);
	  }
	}
      }
      else{
	if(strstr(dp2->d_name,".gel")){
	  if((fileptr = fopen(messprintf("%s/%s",to,dp2->d_name),"r")) == NULL){
	    /* copy this one */
	    sprintf(str1,"cp %s/%s %s/%s",from,dp2->d_name,to,dp2->d_name);
	    system(str1);
	  }
	  else{
	    /* copy but add prefix */
	    sprintf(str1,"cp %s/%s %s/a%s",from,dp2->d_name,to,dp2->d_name);
	    system(str1);
	  }
	}
      }
    }
  }
}

void mergethetwo()
{
  int i;
  struct remark *rem;
  struct fpdata *fp;
  struct markertop *mp;
  CLONE *cloneA,cloneB;
  int index,mergecount= 0,mduplicount= 0;

  for(i=0;i<arrayMax(acedatasecond);i++){
    cloneB=arr(acedatasecond,i,CLONE);
    if(!fppInsert(acedata,cloneB.clone,&index,cloneOrder)){ 
      cloneA=arrp(acedata,index,CLONE);
      rem = cloneA->fp_remark;
      if(rem == NULL){
	cloneA->fp_remark = (struct remark *)messalloc((sizeof(struct remark)));
	rem = cloneA->fp_remark;
      }
      else{
	while(rem->next != NULL)
	  rem = rem->next;
	rem->next = (struct remark *)messalloc((sizeof(struct remark)));
      }
      if(cloneA->ctg != 0 && cloneB.ctg != 0){
	sprintf(rem->message,"Merge %d %d %d %d",cloneA->ctg,cloneA->x,cloneB.ctg,cloneB.x);
	mergecount++;
      }
      else{
	strcpy(rem->message,"MDupli");
	mduplicount++;
      }
      rem->next = cloneB.fp_remark;

      /* add cloneB's remarks */
      rem = cloneA->remark;
      if(rem == NULL){
	cloneA->remark = cloneB.remark;
      }
      else{
	while(rem->next != NULL)
	  rem = rem->next;
	rem->next = cloneB.remark;
      }

      /* add cloneB's gel data */
      fp = cloneA->fp;
      if(fp == NULL)
	cloneA->fp = cloneB.fp;
      else{
	while(fp->next != NULL)
	  fp=fp->next;
	fp->next = cloneB.fp;
      }

      /* add marker data for this clone */
      mp = cloneA->marker;
      if(mp == NULL)
	cloneA->marker = cloneB.marker;
      else{
	while(mp->nextmarker!= NULL)
	  mp=mp->nextmarker;
	mp->nextmarker = cloneB.marker;
      }
  
    }
    else
      array(acedata,index,CLONE) = cloneB;  
  }
  printf("%d clones existed in both projects and in different contigs\n",mergecount);
  printf("    Search FP_remark for 'Merge' \n");
  printf("%d clones existed in both projects and were singletons\n",mduplicount);
  printf("    Search FP_remark for 'MDupli' \n");
  SetCtgForMatchingClones4();
}

void savenew(){

  strcpy(dirName,newdirName);
  strcpy(fileName,newfileName);
  okaytowrite = TRUE;
  if(save_fpc()>0){
    printf("New project saved\n");
    displaymess("New Project Saved");
    menu_main();
  }
  else{
    printf("Failed to save new project\n");
    displaymess("Failed to save new project");
  }
  okaytowrite = FALSE;
  arrayDestroy(acedatasecond);
}

BOOL getfirstcor(){
  int *vp;
  unsigned int nb,size = 2;
  FILE *corfile;
  int i;
  char str1[80];

  if (arrayExists(bands)) return TRUE;

  if(strlen(dirName)>0){
    if((corfile = fopen(messprintf("%s/%s.cor", dirName, fileName),"rb")) == NULL ){
      sprintf(str1,"file %s.cor does not exist?",messprintf("%s/%s", dirName, fileName));
      displaymess(str1);
      
      return FALSE;
    }
    
  }
  else{
    if((corfile = fopen(messprintf("%s.cor", fileName),"rb")) == NULL ){
       sprintf(str1,"file %s.cor does not exist?",messprintf("%s", fileName));
      displaymess(str1);
      return FALSE;
    }
  }
  fseek(corfile, 0, SEEK_END);
  nb = ftell(corfile);
  rewind(corfile);

  nb /= 2;
  bands = arrayCreate(nb, int);
  arrayMax(bands) = nb;

  vp = arrp(bands, 0, int);
  if ((i=fread(vp,size,nb,corfile)) != nb) {
     fprintf(stderr,"Error: cannot read cor file %d %d\n",nb, i);
     return FALSE;
  }
  for (i=0; i< nb; i++) 
		vp[i] = SWAP_HALF(vp[i]);

  filclose(corfile);
     
  bandmax = 0;
  for(i=0;i<arrayMax(bands);i++) bandmax = MaX(bandmax, vp[i]);
  fprintf(stdout, "Max band size %d\n",bandmax);
  return TRUE;
}

BOOL getsecondcor(){
  int *vp;
  unsigned int nb,size = 2;
  FILE *corfile;
  int i;
  char str1[80];
  int bandmax2;

  if(strlen(dirName3)>0){
    if((corfile = fopen(messprintf("%s/%s.cor", dirName3,secondfileName),"rb")) == NULL ){
      sprintf(str1,"file %s.cor does not exist?",messprintf("%s/%s", dirName3, secondfileName));
      displaymess(str1);
      
      return FALSE;
    }
    
  }
  else{
    if((corfile = fopen(messprintf("./%s.cor",secondfileName),"rb")) == NULL ){
      sprintf(str1,"file %s.cor does not exist?",secondfileName);
      displaymess(str1);
      return FALSE;
    }
  }
  fseek(corfile, 0, SEEK_END);
  nb = ftell(corfile);
  rewind(corfile);

  nb /= 2;
  bands_second = arrayCreate(nb, int);
  arrayMax(bands_second) = nb;

  vp = arrp(bands_second, 0, int);
  if ((i=fread(vp,size,nb,corfile)) != nb) {
     fprintf(stderr,"Error: cannot read cor file %d %d\n",nb, i);
     return FALSE;
  }
  for (i=0; i< nb; i++) 
		vp[i] = SWAP_HALF(vp[i]);

  filclose(corfile);
     
  bandmax2 = 0;
  for(i=0;i<arrayMax(bands_second);i++) bandmax2 = MaX(bandmax2, vp[i]);
  fprintf(stdout, "Max band size for second %d\n",bandmax2);
  return TRUE;
}

BOOL mergecorandsave()
{
  int *tmp;
  int i;
  FILE *corfile;
  int max1,max2;

  if(bands){
    if(strlen(dirName)>0){
      if((corfile = fopen(messprintf("%s/../%s/%s.cor", dirName, newfileName,newfileName),"w")) == NULL ){
	printf("could not open %s\n",messprintf("%s/../%s/%s.cor", dirName, newfileName,newfileName));
     return FALSE;
      }
    }
    else{
      if((corfile = fopen(messprintf("../%s/%s.cor", newfileName, newfileName),"w")) == NULL ){
	printf("could not open %s\n",messprintf("../%s/%s.cor", newfileName, newfileName));
	return FALSE;
      }    
    }

    tmp = (int *) malloc(sizeof(int) * (arrayMax(bands)+arrayMax(bands_second)));
    max1 = arrayMax(bands);
    max2 = arrayMax(bands_second);
    for(i=0;i<arrayMax(bands_second);i++)
      array(bands,i+max1,int) = array(bands_second,i,int);

    for (i=0; i< arrayMax(bands); i++) 
      tmp[i] = SWAP_HALF(arr(bands, i, int));

    fwrite(tmp,sizeof(int), arrayMax(bands),corfile);

    free(tmp);

    fclose(corfile);

    return TRUE;
  }
  else 
    return TRUE;
}


void projmergerout()
{
  getnewproj();
}


/**************************************************************
                   DEF: SetCtgForMatchingClones4
**************************************************************/
void SetCtgForMatchingClones4()
/* This routine searches searches for the approxiamate and exact matches.*/
/* The clones that are these, will locate there "Mothers" and load their data */
{
  int i,max,index;
  CLONE *clone, *parent;
  struct remark *rem;

  max= arrayMax(acedata); 
  contigsAlloc(max_contig);
  
  for(i=0;i<max;i++){

    clone =  arrp(acedata, i, CLONE);
    clone->next = -1;
    if(clone->clone[0] == '!') continue;

    if(clone->match[0] != ' '){
      if(!fppFind(acedata,clone->match,&index, cloneOrder)) {
	printf("FPC ERROR could not find clone *%s* parent = %s\n",
		clone->match,clone->clone);
	index = -1;
      }

      if(index!=-1){  
	parent = arrp(acedata,index,CLONE);
	if(parent->match[0] != ' '){
	  if(!fppFind(acedata,parent->match,&index, cloneOrder)) {
	    printf("FPC ERROR(2) could not find clone *%s* parent = %s\n",
		   parent->match,parent->clone);
	    index= -1;
	  }  
	  else
	    parent = arrp(acedata,index,CLONE);
	}
	if(index != -1){
	  clone->parent = index;
	  if(clone->mattype != PSEUDO)
	    parent->mattype = PARENT;
	  else if(!(parent->mattype = PARENT))
	    parent->mattype = PSPARENT;
	  /* sanity checks */
	  if(clone->ctg != parent->ctg){
	    rem = clone->fp_remark;
	    if(rem == NULL){
	      clone->fp_remark = (struct remark *)messalloc((sizeof(struct remark)));
	      rem = clone->fp_remark;
	    }
	    else{
	      while(rem->next != NULL)
		rem = rem->next;
	      rem->next = (struct remark *)messalloc((sizeof(struct remark)));
	    }
	    sprintf(rem->message,"Merge parent in diff ctg %d->%d",clone->ctg,parent->ctg);
	    rem->next = NULL;
	    clone->ctg = parent->ctg;
	    sprintf(clone->chctg,"ctg%d",clone->ctg);	    
	  }
	  if(parent->match[0] != ' ')
	    printf("FPC ERROR clone %s has parent %s who has parent %s\n",
		   parent->clone ,clone->clone, 
		   arrp(acedata,clone->parent, CLONE)->clone);
	  
	}
      }
    }
  }
}

